package main

import (
	"env_serial_wind/config"
	"fmt"
	"github.com/tarm/serial"
	"log"
	"math/rand"
	"strings"
	"sync"
	"time"
)

var gw sync.WaitGroup

func hexCheckSum(data []byte) string {
	var sum byte
	for _, b := range data {
		sum ^= b
	}
	return fmt.Sprintf("%02x", sum)
}

func appendHexCheck(data string) string {
	return data + strings.ToUpper(hexCheckSum([]byte(data[1:len(data)-1]))) + "\r\n"
}

func latLon(min float32, max float32) string {
	randomFloat := min + rand.Float32()*(max-min)
	degrees := int(randomFloat)
	minutes := (randomFloat - float32(degrees)) * 60.0
	ddmmmmmm := float32(degrees)*100.0 + minutes
	return fmt.Sprintf("%.4f", ddmmmmmm)
}

func mockWind(ch chan<- [4]string) {
	index := 0
	gps_mock := [3][2]string{
		// 31.12058023743304, 122.00223775799077 s1  3107.2348 , 12200.1342
		// 31.124534551170825, 122.01811619596705 s2 3107.4721 , 12201.0869
		// 31.11662575892476, 122.01190917021268 标1  3106.9975 , 12200.7146
		{"3107.2348", "12200.1342"},
		{"3107.4721", "12201.0869"},
		{"3106.9975", "12200.7146"},
	}
	for {
		//$WIMWV,065,T,000.64,M,A*09
		//$GPGGA,092422.000,2343.6152,N,11730.0582,E,1,06,1.7,10.7,M,11.5,M,,0000*6D
		var wind [4]string
		wind[0] = "$WIMWV,053,R,001.24,M,A*0F\r\n"
		wimwv := ""
		if config.Conf.FixedWind == 1 {
			wimwv = fmt.Sprintf("$WIMWV,%0.3d,T,%06.2f,M,A*", config.Conf.FixedWindDirection, config.Conf.FixedWindSpeed)
		} else {
			wimwv = fmt.Sprintf("$WIMWV,%0.3d,T,%06.2f,M,A*", rand.Intn(360), rand.Float32()*80)
		}
		wind[1] = appendHexCheck(wimwv)
		dateTime := time.Now().Add(-8 * time.Hour)
		gps := gps_mock[index]
		index = (index + 1) % 3
		gpgga := fmt.Sprintf("$GPGGA,%s.000,%s,N,%s,E,1,05,2.0,24.1,M,7.1,M,,0000*",
			dateTime.Format("150405"),
			gps[0],
			gps[1])
		wind[2] = appendHexCheck(gpgga)
		wind[3] = "$PGILT,A,-04,D,+00,D,+1,TILT*36\r\n"
		ch <- wind
		time.Sleep(time.Second)
	}
}

func consoleWind(ch <-chan [4]string) {
	for {
		data := <-ch
		for _, item := range data {
			fmt.Printf("%s\n", item)
		}
		fmt.Printf("\n")
	}
}

func writeWind(ch <-chan [4]string) {
	serialConfig := &serial.Config{
		Name: config.Conf.SerialName,
		Baud: config.Conf.SerialBaud,
	}
	port, err := serial.OpenPort(serialConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer func(port *serial.Port) {
		err := port.Close()
		if err != nil {
			fmt.Println(err)
		}
	}(port)

	for {
		data := <-ch
		currentTime := time.Now()
		for _, item := range data {
			fmt.Printf("%s:%s=>%s", currentTime.Format("2006-01-02 15:04:05"), config.Conf.SerialName, item)
			_, err := port.Write([]byte(item))
			if err != nil {
				log.Fatal(err)
			}
		}
		fmt.Println()
	}
}

func main() {
	gw.Add(1)
	var windCh = make(chan [4]string, 8)
	go mockWind(windCh)
	go writeWind(windCh)
	gw.Wait()
}
